#include "preHeader.h"
#include "GateServerMgr.h"
#include "Map/InstanceMgr.h"

GateServerMgr::GateServerMgr()
{
}

GateServerMgr::~GateServerMgr()
{
}

void GateServerMgr::RunGC()
{
	while (!m_recycleBin.empty()) {
		auto& pair = m_recycleBin.front();
		if (pair.second < GET_UNIX_TIME) {
			m_recycleBin.pop();
		} else {
			break;
		}
	}
}

void GateServerMgr::RegisterGateServer(GateServerSession* pGateSession)
{
	std::lock_guard<std::shared_mutex> lock(m_GateServerMutex);
	m_GateServerMap.emplace(pGateSession->guid(), pGateSession);
}

void GateServerMgr::RemoveGateServer(GateServerSession* pGateSession)
{
	do {
		std::lock_guard<std::shared_mutex> lock(m_GateServerMutex);
		m_GateServerMap.erase(pGateSession->guid());
		m_recycleBin.emplace(
			pGateSession->GetConnection(), GET_UNIX_TIME + GC_DELAY_TIME);
	} while (0);
	sInstanceMgr.ForeachAllInstance(
		[=, connPtr = pGateSession->GetConnection()](MapInstance* pMapInstance) {
		pMapInstance->EventOfflineGatePlayer(pGateSession);
	});
}

GateServerSession* GateServerMgr::GetGateServer(const GateServerGUID& guid) const
{
	std::shared_lock<std::shared_mutex> lock(m_GateServerMutex);
	auto itr = m_GateServerMap.find(guid);
	return itr != m_GateServerMap.end() ? itr->second : NULL;
}

GateServerSession* GateServerMgr::GetGateServer(uint32 serverId, uint32 gateSN, uint32 msSN) const
{
	GateServerGUID guid;
	guid.serverId = serverId, guid.gateSN = gateSN, guid.msSN = msSN;
	return GetGateServer(guid);
}

void GateServerMgr::BroadcastPacket2AllClient(const INetPacket& data) const
{
	NetPacket pck(SGM_PUSH_PACKET_TO_ALL_CLIENT);
	BroadcastPacket2AllGateServer(pck, data);
}

void GateServerMgr::BroadcastPacket2AllGateServer(const INetPacket& pck) const
{
	std::shared_lock<std::shared_mutex> lock(m_GateServerMutex);
	for (auto& pair : m_GateServerMap) {
		pair.second->PushSendPacket(pck);
	}
}

void GateServerMgr::BroadcastPacket2AllGateServer(
	const INetPacket& pck, const INetPacket& data) const
{
	std::shared_lock<std::shared_mutex> lock(m_GateServerMutex);
	for (auto& pair : m_GateServerMap) {
		pair.second->PushSendPacket(pck, data);
	}
}
